﻿using System;
using System.Collections.Generic;
using System.Linq;
using Assist;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using YJKArchMethodLibrary.Utils;
using TopologySearch;

namespace YJKArchMethodLibrary.Common
{
	public class CurveListHandle
	{
		public static List<Curve> GetOuterOffsetCurves(ExternalCommandData cmdData, List<Curve> oriCurves, double offset)
		{
			if (oriCurves.Count < 3)
			{
				return null;
			}
			UIApplication application = cmdData.Application;
			if (offset < 0.0)
			{
				offset = -offset;
			}
			offset = AssistFunc.mmToFeet(offset);
			List<Curve> curves = CurveListHandle.MergeCurves(application, oriCurves);
			List<Curve> offsetCurves = CurveListHandle.GetOffsetCurves(application, curves, offset);
			List<Curve> linkCurves = CurveListHandle.GetLinkCurves(application, offsetCurves);
			return CurveListHandle.GetOuterClosedAreaCurves(cmdData, linkCurves)[0];
		}

		public static List<Curve> MergeCurves(UIApplication uiApp, List<Curve> curves)
		{
			if (curves.Count < 2)
			{
				return curves;
			}
			Curve curve = curves[0];
			List<Curve> list = new List<Curve>();
			for (int i = 1; i < curves.Count; i++)
			{
				Curve curve2 = CurveAssistFunc.Combine2Curve(uiApp, curve, curves[i]);
				if (null == curve2)
				{
					list.Add(curve);
					curve = curves[i];
				}
				else
				{
					curve = curve2;
				}
			}
			Curve curve3 = CurveAssistFunc.Combine2Curve(uiApp, curve, list[0]);
			if (null == curve3)
			{
				list.Add(curve);
			}
			else
			{
				list.RemoveAt(0);
				list.Add(curve3);
			}
			return list;
		}

		public static List<Curve> GetOffsetCurves(UIApplication uiApp, List<Curve> curves, double offset)
		{
			List<XYZ> list = new List<XYZ>();
			foreach (Curve curve in curves)
			{
				list.Add(curve.GetEndPoint(0));
			}
			EdgeLoopAnalyser.RightHandwise direction = EdgeLoopAnalyser.RightHandwise._AntiClockwise;
			if (!EdgeLoopAnalyser.JudgeRightHandwise(list, ref direction))
			{
				return null;
			}
			return CurveListHandle.GetOffsetCurves(uiApp, curves, offset, direction);
		}

		public static List<Curve> GetOffsetCurves(UIApplication uiApp, List<Curve> curves, double offset, EdgeLoopAnalyser.RightHandwise direction)
		{
			if (EdgeLoopAnalyser.RightHandwise._AntiClockwise == direction)
			{
				offset = -offset;
			}
			List<Curve> list = new List<Curve>();
			foreach (Curve curve in curves)
			{
				Line line = curve as Line;
				if (null != line)
				{
					list.Add(Geometry.OffsetLine(line, offset, null));
				}
				Arc arc = curve as Arc;
				if (null != arc)
				{
					Arc arc2;
					try
					{
						arc2 = Geometry.OffsetArc(uiApp.Application, arc, offset);
					}
					catch (Exception)
					{
						continue;
					}
					if (arc2.XDirection.IsAlmostEqualTo(arc.XDirection) && arc2.YDirection.IsAlmostEqualTo(arc.YDirection))
					{
						list.Add(arc2);
					}
				}
			}
			return list;
		}

		public static List<Curve> GetLinkCurves(UIApplication uiApp, List<Curve> curves)
		{
			curves.Add(curves[0].Clone());
			curves.Add(curves[1].Clone());
			List<Curve> list = new List<Curve>();
			XYZ xyz = curves[0].GetEndPoint(0);
			XYZ xyz2 = curves[0].GetEndPoint(1);
			int i = 0;
			while (i < curves.Count - 1)
			{
				XYZ xyz3 = curves[i + 1].GetEndPoint(0);
				xyz3 = Geometry.IntersectWithTwoCurves(curves[i], curves[i + 1], xyz3, true, true, uiApp.Application);
				xyz2 = (xyz3 ?? curves[i].GetEndPoint(1));
				Line line = curves[i] as Line;
				if (null != line)
				{
					try
					{
						list.Add(Line.CreateBound(xyz, xyz2));
					}
					catch
					{
						goto IL_132;
					}
					goto IL_BE;
				}
				goto IL_BE;
				IL_132:
				i++;
				continue;
				IL_BE:
				Arc arc = curves[i] as Arc;
				if (null != arc)
				{
					try
					{
						XYZ xyz4 = AxisAssistFunc.CalculatMidPoint(xyz, xyz2, arc.Center, arc.Normal);
						list.Add(Arc.Create(xyz, xyz2, xyz4));
					}
					catch
					{
						goto IL_132;
					}
				}
				if (xyz3 == null)
				{
					list.Add(Line.CreateBound(xyz2, curves[i + 1].GetEndPoint(0)));
					xyz2 = curves[i + 1].GetEndPoint(0);
				}
				xyz = xyz2;
				goto IL_132;
			}
			list.RemoveAt(0);
			return list;
		}

		public static List<List<Curve>> GetOuterClosedAreaCurves(ExternalCommandData cmdData, List<Curve> curves)
		{
			List<Pole2D> list = new List<Pole2D>();
			int num = 0;
			foreach (Curve curve in curves)
			{
				Pole2D item = Pole2D.TransformWallToStructure2DPole(curve, new ElementId(num++), 0.0, 0.0);
				list.Add(item);
			}
			return new StructureLoopSearcher(cmdData).GetFullFloorEdgeLoops(list, StructureLoopSearcher.SearchEdgeLocation.SEL_Outside);
		}

		public static List<List<Curve>> GetClosedAreaOuterWallCurves(ExternalCommandData cmdData, List<Wall> walls)
		{
			int num = 0;
			List<Pole2D> list = new List<Pole2D>();
			foreach (Wall wall in walls)
			{
				Pole2D item = Pole2D.TransformWallToStructure2DPole((wall.Location as LocationCurve).Curve, new ElementId(num++), wall.Width / 2.0, wall.Width / 2.0);
				list.Add(item);
			}
			return new StructureLoopSearcher(cmdData).GetFullFloorEdgeLoops(list, StructureLoopSearcher.SearchEdgeLocation.SEL_Outside);
		}

		public static List<Curve> GetOuterWallByPoint(ExternalCommandData cmdData, XYZ ptInArea)
		{
			foreach (List<Curve> list in CurveListHandle.GetAllOuterWallCurves(cmdData))
			{
				List<XYZ> list2 = new List<XYZ>();
				foreach (Curve curve in list)
				{
					list2.AddRange(curve.Tessellate());
				}
				if (Geometry.PointInPloygon(list2, ptInArea, 0.0001, 0.0001) == 1)
				{
					return list;
				}
			}
			return null;
		}

		public static List<List<Curve>> GetAllOuterWallCurves(ExternalCommandData cmdData)
		{
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(cmdData.Application.ActiveUIDocument.Document);
			filteredElementCollector.OfClass(typeof(Wall));
			List<Wall> list = filteredElementCollector.Cast<Wall>().ToList<Wall>();
			int num = 0;
			List<Pole2D> list2 = new List<Pole2D>();
			foreach (Wall wall in list)
			{
				Pole2D item = Pole2D.TransformWallToStructure2DPole((wall.Location as LocationCurve).Curve, new ElementId(num++), wall.Width / 2.0, wall.Width / 2.0);
				list2.Add(item);
			}
			return new StructureLoopSearcher(cmdData).GetFullFloorEdgeLoops(list2, StructureLoopSearcher.SearchEdgeLocation.SEL_Outside);
		}
	}
}
